home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / fatal13.arc / FATAL.ASM next >
Encoding:
Assembly Source File  |  1989-08-30  |  35.0 KB  |  1,360 lines

  1. page 66,132
  2. ;
  3. ; Resident Critical Error Handler
  4. ;
  5. ; This program is a TSR that traps critical errors and attempts
  6. ; to handle them in an intelligent way.
  7. ;
  8. ; It draws on all available information to present a complete error
  9. ; description to the user, and to provide sensible default actions
  10. ; when the operator is not present.
  11. ;
  12. ; Copyright 1989 Samuel H. Smith; All rights reserved.
  13. ;
  14. ;------------------------------------------------
  15. ;
  16. ;                                  LICENSE
  17. ;                                  =======
  18. ;  SourceWare: What is it?
  19. ;  -----------------------
  20. ;
  21. ;  SourceWare is my name for a unique concept in user supported
  22. ;  software.
  23. ;
  24. ;  Programs distributed under the SourceWare concept always offer source
  25. ;  code.
  26. ;
  27. ;  This package can be freely distributed so long as it is not modified
  28. ;  or sold for profit.  If you find that this program is valuable, you
  29. ;  can send me a donation for what you think it is worth.  I suggest
  30. ;  about $10.
  31. ;
  32. ;  Send your contributions to:
  33. ;     Samuel H. Smith                 The Tool Shop BBS
  34. ;     5119 N. 11th Ave., #332         (602) 264-3969 (2400) - Free node
  35. ;     Phoenix AZ 85013                (602) 279-0230 (HAYES 9600)
  36. ;                                     (602) 279-2673 (HST 9600)
  37. ;
  38. ;  Why SourceWare?
  39. ;  ---------------
  40. ;  Why do I offer source code?  Why isn't the donation manditory?  The
  41. ;  value of good software should be self-evident.  The source code is
  42. ;  the key to complete understanding of a program.  You can read it to
  43. ;  find out how things are done.  You can also change it to suit your
  44. ;  needs, so long as you do not distribute the modified version without
  45. ;  my consent.
  46. ;
  47. ;
  48. ;  Copyright
  49. ;  ---------
  50. ;  If you modify this program,  I would appreciate a copy of the new
  51. ;  source code.  I am holding the copyright on the source code,  so
  52. ;  please don't delete my name from the program files or from the
  53. ;  documentation.
  54. ;
  55. ;                               DISCLAIMER
  56. ;                               ==========
  57. ;  I make no warranty of any kind, express or implied, including without
  58. ;  limitation, any warranties of merchantability and/or fitness for a
  59. ;  particular purpose.  I shall not be liable for any damages, whether
  60. ;  direct, indirect, special or consequential arising from a failure of
  61. ;  this program to operate in the manner desired by the user.  I shall
  62. ;  not be liable for any damage to data or property which may be caused
  63. ;  directly or indirectly by the use of this program.
  64. ;
  65. ;  IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY
  66. ;  LOST PROFITS,  LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL
  67. ;  DAMAGES ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR
  68. ;  FOR ANY CLAIM BY ANY OTHER PARTY.
  69. ;
  70.  
  71. %newpage
  72. ;------------------------------------------------
  73. ; macro- push all registers
  74. ;
  75. pushall macro
  76.         push ax
  77.         push bx
  78.         push cx
  79.         push dx
  80.         push ds
  81.         push es
  82.         push si
  83.         push di
  84.         push bp
  85. endm
  86.  
  87. ;------------------------------------------------
  88. ; macro- pop all registers
  89. ;
  90. popall macro
  91.         pop bp
  92.         pop di
  93.         pop si
  94.         pop es
  95.         pop ds
  96.         pop dx
  97.         pop cx
  98.         pop bx
  99.         pop ax
  100. endm
  101.  
  102. ;------------------------------------------------
  103. ; macro- clear register
  104. ;
  105. clr macro reg
  106.         xor reg,reg
  107. endm
  108.  
  109.  
  110. ;------------------------------------------------
  111. ; macro- dos function call
  112. ;
  113. dosDisplay     = 9h
  114. dosSetvec      = 25h
  115. dosGetvers     = 30h
  116. dosGetvec      = 35h
  117. dosFreemem     = 49h
  118. dosExit        = 4ch
  119. dosErrinfo     = 59h
  120.  
  121. msdos   macro funct,param
  122.         ifb <param>
  123.            mov ah,funct
  124.         else
  125.            mov ax,(funct*100h)+param
  126.         endif
  127.         int 21h
  128. endm
  129.  
  130. ;------------------------------------------------
  131. ; macro- get vector
  132. ; exit: vector stored in 'dword ptr ds:dest'
  133. ;
  134. getvect macro vectnum,dest
  135.         msdos dosGetvec,vectnum
  136.         mov word ptr dest,bx
  137.         mov word ptr dest+2,es
  138. endm
  139.  
  140. ;------------------------------------------------
  141. ; macro- set vector
  142. ;
  143. setvect macro vectnum,handler
  144.         lea dx,handler
  145.         msdos dosSetvec,vectnum
  146. endm
  147.  
  148.  
  149. ;------------------------------------------------
  150. ; macro- restore original vector
  151. ;
  152. revect macro vectnum,ohandler
  153.         lds dx,es:ohandler
  154.         msdos dosSetvec,vectnum
  155. endm
  156.  
  157.  
  158. ;------------------------------------------------
  159. ; macro- video function call
  160. ;
  161. vidSetcu       = 02h
  162. vidGetcu       = 03h
  163. vidGetch       = 08h
  164. vidPutch       = 09h
  165. vidTty         = 0eh
  166.  
  167. video   macro funct
  168.         mov ah,funct
  169.         int 10h
  170. endm
  171.  
  172. ;------------------------------------------------
  173. ; macro- keyboard function call
  174. ;
  175. kbdGetch       = 0
  176. kbdStatus      = 1
  177.  
  178. keybd   macro funct
  179.         mov ah,funct
  180.         int 16h
  181. endm
  182.  
  183. %newpage
  184. ;------------------------------------------------
  185. ; program segment prefix
  186. ;
  187. code segment
  188.         assume cs:code, ds:nothing, es:nothing, ss:nothing
  189.  
  190.         org 012h
  191. int24p  dd      ?       ;pointer to current int24 handler
  192.  
  193.         org 02ch
  194. envseg  dw      ?       ;environment segment number
  195.  
  196.         org 80h
  197. tailLen db      ?       ;command tail length
  198. tail    db      ?
  199.  
  200.         org 100h
  201. entry:
  202.         jmp entryPoint
  203.  
  204.  
  205. ;------------------------------------------------
  206.  
  207. errorCount     dw      0       ;count of errors intercepted
  208. autoCount      dw      0       ;count of automatic retries
  209. ;hookCount      dw      0       ;count of int24 hookups
  210.  
  211.  
  212. ;------------------------------------------------
  213.  
  214. signature       db 13,10,'Resident Critical Error Handler v1.3 ',??DATE
  215.                 db 13,10,'Copyright 1989 Samuel H. Smith; ALL RIGHTS RESERVED'
  216.                 db 13,10
  217. crlfs           db 13,10,'$'
  218.  
  219.  
  220. %newpage
  221. ;------------------------------------------------
  222. ; table format:
  223. ;       db 'initial message....$'
  224. ;       db 80h+code,0,'message....$'
  225. ;       db 80h+code,0,'message....$'
  226. ;       db 0,0,'last message$'
  227. ;
  228. ; table of extended error messages
  229. ;
  230. errorNames     db 'Error: $'
  231. ;               db 80h+01h,0,'Function number invalid!$'
  232. ;               db 80h+02h,0,'File not found!$'
  233. ;               db 80h+03h,0,'Path not found!$'
  234. ;               db 80h+04h,0,'Too many open files (no handles available)!$'
  235.                 db 80h+05h,0,'Access denied!$'
  236. ;               db 80h+06h,0,'Invalid handle!$'
  237. ;               db 80h+07h,0,'Memory control block destroyed!$'
  238. ;               db 80h+08h,0,'Insufficient memory!$'
  239. ;               db 80h+09h,0,'Memory block address invalid!$'
  240. ;               db 80h+0Ah,0,'Environment invalid!$'
  241. ;               db 80h+0Bh,0,'Format invalid!$'
  242. ;               db 80h+0Ch,0,'Access code invalid!$'
  243. ;               db 80h+0Dh,0,'Data invalid!$'
  244. ;               db 80h+0Fh,0,'Invalid drive!$'
  245. ;               db 80h+10h,0,'Attempted to remove current directory!$'
  246. ;               db 80h+11h,0,'Not same device!$'
  247. ;               db 80h+12h,0,'No more matching files!$'
  248.  
  249.                 db 80h+13h,0,'Disk write-protected!$'
  250.                 db 80h+14h,0,'Unknown unit!$'
  251.                 db 80h+15h,0,'Drive not ready!$'
  252. ;               db 80h+16h,0,'Unknown command!$'
  253.                 db 80h+17h,0,'Data error (CRC)!$'
  254. ;               db 80h+18h,0,'Bad request structure length!$'
  255.                 db 80h+19h,0,'Seek error!$'
  256.                 db 80h+1Ah,0,'Unknwon media type (non-DOS disk)!$'
  257.                 db 80h+1Bh,0,'Sector not found!$'
  258.                 db 80h+1Ch,0,'Printer out of paper!$'
  259.                 db 80h+1Dh,0,'Write fault!$'
  260.                 db 80h+1Eh,0,'Read fault!$'
  261.                 db 80h+1Fh,0,'General failure!$'
  262.  
  263.                 db 80h+20h,0,'Sharing violation!$'
  264.                 db 80h+21h,0,'Lock violation!$'
  265.                 db 80h+22h,0,'Invalid disk change!$'
  266. ;               db 80h+23h,0,'No FCB available!$'
  267.                 db 80h+24h,0,'Sharing buffer overflow!$'
  268.  
  269. ;               db 80h+32h,0,'Network request not supported!$'
  270.                 db 80h+33h,0,'Remote computer not listening!$'
  271. ;               db 80h+34h,0,'Duplicate name on network!$'
  272.                 db 80h+35h,0,'Network name not found!$'
  273.                 db 80h+36h,0,'Network busy!$'
  274.                 db 80h+37h,0,'Network device no longer exists!$'
  275. ;               db 80h+38h,0,'Network BIOS command limit exceeded!$'
  276.                 db 80h+39h,0,'Network adapter hardware error!$'
  277.                 db 80h+3Ah,0,'Incorrect response from network!$'
  278.                 db 80h+3Bh,0,'Unexpected network error!$'
  279. ;               db 80h+3Ch,0,'Incompatible remote adapter!$'
  280.                 db 80h+3Dh,0,'Print queue full!$'
  281. ;               db 80h+3Eh,0,'Queue not full!$'
  282.                 db 80h+3Fh,0,'Not enough space to print file!$'
  283.                 db 80h+40h,0,'Network name was deleted!$'
  284.                 db 80h+41h,0,'Access denied by network!$'
  285. ;               db 80h+42h,0,'Network device type incorrect!$'
  286.                 db 80h+43h,0,'Network name not found!$'
  287. ;               db 80h+44h,0,'Network name limit exceeded!$'
  288. ;               db 80h+45h,0,'Network BIOS session limit exceeded!$'
  289. ;               db 80h+46h,0,'Temporarily paused!$'
  290.                 db 80h+47h,0,'Network request not accepted!$'
  291. ;               db 80h+48h,0,'Print/disk redirection paused!$'
  292.                 db 80h+50h,0,'File already exists!$'
  293. ;               db 80h+52h,0,'Cannot make directory!$'
  294. ;               db 80h+53h,0,'Fail on INT 24h!$'
  295. ;               db 80h+54h,0,'Too many redirections!$'
  296. ;               db 80h+55h,0,'Duplicate redirection!$'
  297. ;               db 80h+56h,0,'Invalid password!$'
  298. ;               db 80h+57h,0,'Invalid parameter!$'
  299.                 db 80h+58h,0,'Network write fault!$'
  300.                 db 0,0,'Undefined!$'
  301.  
  302.  
  303. ;------------------------------------------------
  304. ; table of error areas
  305. ;
  306. driveNames      db 'drive $'
  307.                 db 80h+'A',0,'A:$'
  308.                 db 80h+'B',0,'B:$'
  309.                 db 80h+'C',0,'C:$'
  310.                 db 80h+'D',0,'D:$'
  311.                 db 80h+'E',0,'E:$'
  312.                 db 80h+'F',0,'F:$'
  313.                 db 80h+'G',0,'G:$'
  314.                 db 80h+'G',0,'G:$'
  315.                 db 80h+'I',0,'I:$'
  316.                 db 80h+'J',0,'J:$'
  317.                 db 80h+'K',0,'K:$'
  318.                 db 80h+'L',0,'L:$'
  319.                 db 80h+'M',0,'M:$'
  320.                 db 80h+'N',0,'N:$'
  321.                 db 80h+'O',0,'O:$'
  322.                 db 80h+'P',0,'P:$'
  323.                 db 80h+'Q',0,'Q:$'
  324.                 db 80h+'R',0,'R:$'
  325.                 db 80h+'S',0,'S:$'
  326.                 db 80h+'T',0,'T:$'
  327.                 db 80h+'U',0,'U:$'
  328.                 db 80h+'V',0,'V:$'
  329.                 db 80h+'W',0,'W:$'
  330.                 db 80h+'X',0,'X:$'
  331.                 db 80h+'Y',0,'Y:$'
  332.                 db 80h+'Z',0,'Z:$'
  333.                 db 0,0,'?:$'
  334.  
  335. areaPrefix      db 'Area:  $'
  336. readMsg         db 'Reading from $'
  337. writeMsg        db 'Writing to $'
  338.  
  339. areaNames       db ' $'
  340.                 db 80h+00h,0,'DOS reserved area.$'
  341.                 db 80h+01h,0,'File allocation table.$'
  342.                 db 80h+02h,0,'Directory area.$'
  343.                 db 80h+03h,0,'Data area.$'
  344.                 db 0,0,'Undefined.$'
  345.  
  346. charMsg         db 'character device '
  347. deviceName      db 'DEV.$'
  348. device_driver   dd      0
  349.  
  350.  
  351. ;------------------------------------------------
  352. ; table of error classes
  353. ;
  354. classNames      db 'Class: $'
  355.                 db 80h+00h,0,'[0]$'
  356.                 db 80h+01h,0,'Out of storage space or I/O channels$'
  357.                 db 80h+02h,0,'Temporary situation (file or record lock)$'
  358.                 db 80h+03h,0,'Authorization (denied access)$'
  359.                 db 80h+04h,0,'Internal (system software bug)$'
  360.                 db 80h+05h,0,'Hardware failure$'
  361.                 db 80h+06h,0,'System failure (or bad config file)$'
  362.                 db 80h+07h,0,'Application program error$'
  363.                 db 80h+08h,0,'Item not found$'
  364.                 db 80h+09h,0,'Bad format$'
  365.                 db 80h+0Ah,0,'Resource locked$'
  366.                 db 80h+0Bh,0,'Media error$'
  367.                 db 80h+0Ch,0,'Item already exists$'
  368.                 db 80h+0Dh,0,'Unknown$'
  369.                 db 80h+0Eh,0,'[E]$'
  370.                 db 80h+0Fh,0,'[F]$'
  371.                 db 0,0,'Undefined$'
  372.  
  373.  
  374. ;------------------------------------------------
  375. ; table of error locus codes
  376. ;
  377. locusNames      db ' in $'
  378.                 db 80h+00h,0,'[0]$'
  379.                 db 80h+01h,0,'Unknown.$'
  380.                 db 80h+02h,0,'Block device (disk error).$'
  381.                 db 80h+03h,0,'Network.$'
  382.                 db 80h+04h,0,'Serial device (timeout).$'
  383.                 db 80h+05h,0,'System memory.$'
  384.                 db 80h+06h,0,'[6]$'
  385.                 db 80h+07h,0,'[7]$'
  386.                 db 80h+08h,0,'[8]$'
  387.                 db 0,0,'Undefined.$'
  388.  
  389.  
  390. ;------------------------------------------------
  391. ; table of suggested actions
  392. ;
  393. suggestNames    db 'Suggested action: $'
  394.                 db 80h+01h,0,'Retry the operation.$'
  395.                 db 80h+02h,0,'Delay and then retry.$'
  396.                 db 80h+03h,0,'Re-enter input.$'
  397.                 db 80h+04h,0,'Abort after cleanup.$'
  398.                 db 80h+05h,0,'Immediately abort.$'
  399.                 db 80h+06h,0,'Ignore the error.$'
  400.                 db 80h+07h,0,'Retry after correcting the error.$'
  401.                 db 0,0,'Undefined.$'
  402.  
  403.  
  404. ;------------------------------------------------
  405. ; default actions
  406. ;       01h retry
  407. ;       02h delayed retry
  408. ;       03h prompt user to reenter input
  409. ;       04h abort after cleanup
  410. ;       05h immediate abort
  411. ;       06h ignore
  412. ;       07h retry after user intervention
  413. ;                   ?RRRAAIR
  414. default_actions db '?RRRRAIR'
  415.  
  416. actionPrefix    db '    Action: (A)bort, (R)etry, (I)gnore, (F)ail? <'
  417. default_action  db ?,'> '
  418.                 db 12 dup (' ')
  419.                 db 12 dup (8)
  420. beep            db 7,'$'
  421.  
  422. ;action_echo    db ?,13,10,13,10,'$'
  423.  
  424. ;allowed_actions db      0
  425.  
  426.  
  427. ;------------------------------------------------
  428. ;
  429. box_top         db '  ╔═══════════════════╡ CRITICAL ERROR! ╞════════════════════╗  '
  430. box_side        db 13,10
  431.                 db '                                                             ║  ',13
  432.                 db '  ║  $'
  433. box_bottom      db 13,10
  434.                 db '  ╚══════════════════════════════════════════════════════════╝  '
  435.                 db 13,10,'$'
  436.  
  437. timeoutCount    = 546           ;18.2 * 30 = 30 second delay
  438. tickCount       dw      0
  439.  
  440. message_color   = 70h           ;reverse black on white
  441. save_lines      = 7
  442. save_cols       = 66
  443.  
  444. save_size       = (save_cols*save_lines)
  445. screen_save     dw      save_size dup ('SH')
  446.  
  447. cursor_save     dw      0
  448.  
  449. old_int08       dd      0
  450. old_int1c       dd      0
  451. old_int21       dd      0
  452. old_int24       dd      0
  453.  
  454.  
  455. %newpage
  456. ;=============================================
  457. ; INT 24 - FATAL ERROR HANDLER
  458. ;
  459. int24_handler proc near
  460.         push ds
  461.  
  462.         push cs
  463.         pop ds
  464.         assume ds:code
  465.  
  466. ;       mov allowed_actions,ah
  467.         mov word ptr device_driver,si
  468.         mov word ptr device_driver+2,bp
  469.  
  470.         inc errorCount
  471.         call save_screen
  472.         call report_error_details
  473.         call determine_action
  474.         call restore_screen
  475.  
  476.         pop ds
  477.         iret
  478. int24_handler endp
  479.  
  480.  
  481.  
  482. ;---------------------------------------------
  483. ;  AH: bit 7 = 0 disk I/O error
  484. ;            = 1 other error -- if block device, bad FAT
  485. ;                            -- if char device, code in DI
  486. ;      bit 6  unused
  487. ;      bit 5 = 1 if Ignore allowed, 0 if not (DOS 3+)
  488. ;      bit 4 = 1 if Retry allowed, 0 if not (DOS 3+)
  489. ;      bit 3 = 1 if Fail allowed, 0 if not (DOS 3+)
  490. ;      bit 2 \ disk area of error  00 = DOS area  01 = FAT
  491. ;      bit 1 /                     10 = root dir  11 = data area
  492. ;      bit 0 = 1 if write, 0 if read
  493. ;
  494. ;  AL = drive number if AH bit 7 = 1, otherwise undefined
  495. ;
  496. ;  BP:SI -> header of device driver for which error occurred
  497. ;           block device if high bit of BP:[SI+4] set
  498. ;
  499. report_error_area proc near
  500.         push ax
  501.  
  502.         lea si,box_side
  503.         call display_string
  504.  
  505.         lea si,areaPrefix
  506.         call display_string
  507.  
  508.         lea si,readMsg                 ;display "read" or "write"
  509.         test ah,1
  510.         jz not_write
  511.         lea si,writeMsg
  512.  
  513. not_write:
  514.         call display_string
  515.  
  516.         test ah,80h
  517.         jz is_disk
  518.  
  519.         push ds
  520.         assume ds:nothing
  521.  
  522.         lds si,device_driver
  523.         add si,0ah                      ;start of device name
  524.  
  525.         lea di,deviceName
  526.         push cs
  527.         pop es
  528.  
  529.         movsb                           ;copy 3 bytes
  530.         movsb
  531.         movsb
  532.  
  533.         pop ds
  534.         assume ds:code
  535.  
  536.         lea si,charMsg                 ;display "in serial device"
  537.         call display_string
  538.         jmp  report_end
  539.  
  540. is_disk:
  541.         push ax
  542.         add al,'A'                      
  543.         mov ah,al
  544.         lea si,driveNames
  545.         call table_lookup               
  546.         pop ax
  547.  
  548.         shr ah,1                        ;display area code
  549.         and ah,3
  550.         lea si,areaNames
  551.         call table_lookup               
  552.  
  553. report_end:
  554.         pop ax
  555.         ret
  556. report_error_area endp
  557.  
  558.  
  559. ; ---------------------------------------------
  560. ;
  561. report_error_details proc near
  562.         pushall
  563.         push ax
  564.  
  565.         lea si,box_top
  566.         call display_string
  567.  
  568.         clr bx
  569.         msdos dosErrinfo
  570.  
  571.         lea si,errorNames              ;error [what]
  572.         mov ah,al
  573.         call table_lookup
  574.  
  575.         pop ax
  576.         call report_error_area          ;while read/write disk area
  577.  
  578.         lea si,box_side
  579.         call display_string
  580.  
  581.         mov ah,bh
  582.         lea si,classNames              ;class: out of storage, etc.
  583.         call table_lookup
  584.  
  585.         mov ah,ch
  586.         lea si,locusNames              ;in block device/network/serial
  587.         call table_lookup
  588.  
  589.         lea si,box_side
  590.         call display_string
  591.  
  592.         clr bh                          
  593.         mov al,default_actions[bx]      ;lookup default action from table
  594.         mov default_action,al
  595.  
  596.         mov ah,bl
  597.         lea si,suggestNames
  598.         call table_lookup
  599.  
  600.         popall
  601.         ret
  602. report_error_details endp
  603.  
  604.  
  605.  
  606. ; ---------------------------------------------
  607. ; Handler must return:
  608. ;
  609. ; suggested action codes
  610. ;       01h retry
  611. ;       02h delayed retry
  612. ;       03h prompt user to reenter input
  613. ;       04h abort after cleanup
  614. ;       05h immediate abort
  615. ;       06h ignore
  616. ;       07h retry after user intervention
  617. ;
  618. ; exit: AL = 00 ignore error
  619. ;          = 01 retry operation
  620. ;          = 02 terminate program through INT 22h
  621. ;          = 03 fail system call in progress (DOS 3+)
  622. ;
  623. ; allowed_actions
  624. ;       bit 5 = 1 if Ignore allowed, 0 if not (DOS 3+)
  625. ;       bit 4 = 1 if Retry allowed,  0 if not (DOS 3+)
  626. ;       bit 3 = 1 if Fail allowed,   0 if not (DOS 3+)
  627. ;
  628.  
  629. determine_action proc near
  630.         lea si,box_bottom
  631.         call display_string
  632.  
  633.         lea si,actionPrefix
  634.         call display_string
  635.  
  636.         call flush_key
  637.  
  638. get_action:
  639.         call get_key
  640.  
  641.         mov al,0
  642.         cmp ah,'I'
  643.         jz action_ok
  644.  
  645.         inc al
  646.         cmp ah,'R'
  647.         jz action_ok
  648.  
  649.         inc al
  650.         cmp ah,'A'
  651.         jz action_ok
  652.  
  653.         inc al
  654.         cmp ah,'F'
  655.         jz action_ok
  656.  
  657.         lea si,beep
  658.         call display_string
  659.  
  660.         jmp get_action
  661.  
  662. action_ok:
  663. ;       mov action_echo,ah
  664. ;       lea si,action_echo
  665. ;       call display_string
  666.         ret
  667. determine_action endp
  668.  
  669. %newpage
  670. ; =============================================
  671. ; get keyboard input.  provide default after delay
  672. ;
  673. get_key proc near
  674.         mov tickCount,0
  675.  
  676. get_wait:
  677.         cmp tickCount,timeoutCount
  678.         jge automatic_default
  679.  
  680.         keybd kbdStatus
  681.         jz get_wait
  682.  
  683.         keybd kbdGetch
  684.  
  685.         cmp al,13       ;convert <enter> to default action
  686.         jz  use_default
  687.  
  688.         and al,5fh      ;map to upper case
  689.         mov ah,al
  690.         ret
  691.  
  692. automatic_default:
  693.         inc autoCount
  694. use_default:
  695.         mov ah,default_action
  696.         ret
  697. get_key endp
  698.  
  699.  
  700. ; =============================================
  701. ; flush keyboard buffer - discard type ahead
  702. ;
  703. flush_key proc near
  704. flush_next:
  705.         keybd kbdStatus
  706.         jz flush_exit
  707.  
  708.         keybd kbdGetch
  709.         jmp flush_next
  710.  
  711. flush_exit:
  712.         ret
  713. flush_key endp
  714.  
  715.  
  716. ;------------------------------------------------
  717. ; display buffer using message_color
  718. ; entry: ds:si -> message
  719. ;
  720. display_string proc near
  721.         push ax
  722.         push bx
  723.         push cx
  724.  
  725. disp_next:
  726.         lodsb
  727.         cmp al,'$'
  728.         jz disp_exit
  729.  
  730.         cmp al,7        ;bell
  731.         jz nocolor
  732.         cmp al,8        ;backspace
  733.         jz nocolor
  734.         cmp al,10       ;linefeed
  735.         jz nocolor
  736.         cmp al,13       ;return
  737.         jz nocolor
  738.  
  739.         clr bh
  740.         mov bl,message_color
  741.         mov cx,1
  742.         video vidPutch
  743.  
  744. nocolor:
  745.         mov bl,message_color
  746.         video vidTty
  747.         jmp disp_next
  748.  
  749. disp_exit:
  750.         pop cx
  751.         pop bx
  752.         pop ax
  753.         ret
  754. display_string endp
  755.  
  756.  
  757. ;-------------------------------------------------------------
  758. ; table_lookup
  759. ;
  760. ; entry:        ds:si = table head
  761. ;               ah    = entry code
  762. ;
  763. table_lookup proc near
  764.         assume ds:code
  765.         push si
  766.         call display_string     ;display initial message from table
  767.         pop si
  768.  
  769.         add ah,80h              ;adjust for 80h+ in table codes
  770.  
  771. next:
  772.         lodsb                   ;skip to the end of the message
  773.         cmp al,'$'
  774.         jnz next
  775.  
  776.         lodsb                   ;get entry code
  777.         cmp al,0
  778.         jz Found
  779.  
  780.         cmp al,ah
  781.         jnz next
  782.  
  783. found:
  784.         inc byte ptr [si]       ;count this message
  785.         inc si                  ;and skip the counter
  786.         call display_string     ;display what was found
  787.         ret
  788. table_lookup endp
  789.  
  790.  
  791.  
  792. ; ---------------------------------------------
  793. ; save user screen
  794. ;
  795. save_screen proc near
  796.         assume ds:code
  797.         pushall
  798.  
  799.         clr bx
  800.         video vidGetcu
  801.         mov cursor_save,dx
  802.  
  803.         push cs
  804.         pop es
  805.         lea di,screen_save
  806.         clr dx
  807.  
  808. next_line:
  809.         call save_line
  810.         inc dh
  811.         cmp dh,save_lines
  812.         jnz next_line
  813.  
  814.         clr bx
  815.         clr dx
  816.         video vidSetcu
  817.  
  818.         popall
  819.         ret
  820. save_screen endp
  821.  
  822.  
  823. ; ---------------------------------------------
  824. ; save line
  825. ;
  826. ; entry:        es:di   buffer
  827. ;               dx      starting cursor
  828. ; exit:         saves dh,si
  829. ;
  830. save_line proc near
  831.         assume ds:code
  832.         clr dl
  833.  
  834. next_col:
  835.         push dx
  836.         clr bx
  837.         video vidSetcu
  838.  
  839.         video vidGetch
  840.         stosw
  841.  
  842.         pop dx
  843.         inc dl
  844.         cmp dl,save_cols
  845.         jnz next_col
  846.  
  847.         ret
  848. save_line endp
  849.  
  850.  
  851. ; ---------------------------------------------
  852. ; restore user screen
  853. ;
  854. restore_screen proc near
  855.         assume ds:code
  856.         pushall
  857.  
  858.         lea si,screen_save
  859.         clr dx
  860.  
  861. rnext_line:
  862.         call restore_line
  863.         inc dh
  864.         cmp dh,save_lines
  865.         jnz rnext_line
  866.  
  867.         mov dx,cursor_save
  868.         clr bx
  869.         video vidSetcu
  870.         popall
  871.         ret
  872. restore_screen endp
  873.  
  874.  
  875. ; ---------------------------------------------
  876. ; restore line
  877. ;
  878. ; entry:        ds:si   buffer
  879. ;               dx      starting cursor
  880. ; exit:         saves dh,si
  881. ;
  882. restore_line proc near
  883.         assume ds:code
  884.         clr dl
  885.  
  886. rnext_col:
  887.         push dx
  888.         clr bx
  889.         video vidSetcu
  890.  
  891.         lodsw
  892.         mov bl,ah
  893.         mov cx,1
  894.         video vidPutch
  895.  
  896.         pop dx
  897.         inc dl
  898.         cmp dl,save_cols
  899.         jnz rnext_col
  900.  
  901.         ret
  902. restore_line endp
  903.  
  904.  
  905. %newpage
  906. ; ---------------------------------------------
  907. ; INT 08H - HARDWARE CLOCK TICK HANDLER
  908. ;
  909. ; Count passing clock ticks while attempting to re-install fatal
  910. ; error handler.  
  911. ;
  912. int08_handler proc far
  913.         assume ds:nothing
  914.         inc tickCount          ;count clock ticks-- used to detect timeout
  915.         call install_handler
  916.         jmp old_int08
  917. int08_handler endp
  918.  
  919.  
  920. ; ---------------------------------------------
  921. ; INT 1cH - USER CLOCK TICK HANDLER
  922. ;
  923. ; Count passing clock ticks while attempting to re-install fatal
  924. ; error handler.  
  925. ;
  926. ;int1c_handler proc far
  927. ;        assume ds:nothing
  928. ;        inc tickCount          ;count clock ticks-- used to detect timeout
  929. ;       call install_handler
  930. ;        jmp old_int1c
  931. ;int1c_handler endp
  932.  
  933.  
  934. ; ---------------------------------------------
  935. ; INT 21H - DOS FUNCTION HANDLER
  936. ;
  937. ; Attempt to re-install fatal error handler.
  938. ;
  939. int21_handler proc far
  940.        call install_handler
  941.        jmp old_int21
  942. int21_handler endp
  943.  
  944.  
  945. ; ---------------------------------------------
  946. ; Attempt to re-install fatal error handler.  This is required
  947. ; because command.com tends to over-ride any resident error handlers.
  948. ;
  949. install_handler proc near
  950.         push es
  951.         push dx
  952.         push ax
  953.  
  954.         clr ax                  ;find current fatal handler
  955.         mov es,ax
  956.         les dx,es:[24h*4]
  957.  
  958.         mov ax,es               ;keep new handler if it is loaded after us
  959.         mov dx,cs
  960.         cmp ax,dx
  961.         ja keep
  962.  
  963.                                 ;if dos or command.com stole the handler,
  964.         clr ax                  ;we now take it back.  this also performs
  965.         mov es,ax               ;the initial installation upon startup
  966.         mov word ptr es:[24h*4],offset int24_handler
  967.         mov word ptr es:[24h*4+2],cs
  968. ;        inc hookCount
  969.  
  970. keep:   pop ax
  971.         pop dx
  972.         pop es
  973.         ret
  974. install_handler endp
  975.  
  976.  
  977. %newpage
  978. ; =============================================
  979. ; end of resident portion of code
  980. ;
  981. resident:
  982.  
  983. ; calculate size of resident portion in bytes and segments
  984.  
  985. fatal_size = (offset(resident)-offset(entry))
  986. fatal_segs = (fatal_size / 16) + 32
  987.  
  988.  
  989. ; initialization messages
  990.  
  991. license         db 'This program can be freely distributed so long as it is not modified',13,10
  992.                 db 'or sold for profit.  If you find that this program is valuable, you',13,10
  993.                 db 'can send me a donation for what you think it is worth.  I suggest',13,10
  994.                 db 'about 10 dollars.',13,10
  995.                 db 13,10
  996.                 db 'Send your registrations to:        The Tool Shop BBS',13,10
  997.                 db '   Samuel H. Smith                 (602) 264-3969 (2400) - Free node',13,10
  998.                 db '   5119 N. 11th Ave., #332         (602) 279-2673 (HST 9600)',13,10
  999.                 db '   Phoenix AZ 85013                (602) 279-0230 (HAYES 9600)',13,10
  1000.                 db 13,10
  1001.                 db 'IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY',13,10
  1002.                 db 'LOST PROFITS,  LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL',13,10
  1003.                 db 'DAMAGES ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR',13,10
  1004.                 db 'FOR ANY CLAIM BY ANY OTHER PARTY.',13,10
  1005.                 db 13,10
  1006.  
  1007. usages          db 'Usage:  FATAL/I     ;install in memory.',13,10
  1008.                 db '        FATAL/U     ;un-install.',13,10
  1009.                 db '        FATAL/C     ;display critical error count.'
  1010.                 db 13,10,'$'
  1011.  
  1012. need_dos30      db 'DOS 3.0 or later required!',13,10,'$'
  1013.  
  1014. fatal_loaded    db 'FATAL v1.3 installed.',13,10,'$'
  1015. fatal_removed   db 'FATAL unInstalled.',13,10,'$'
  1016. others_loaded   db 'Other programs loaded after FATAL -- cannot unInstall.',13,10,'$'
  1017. already_loaded  db 'Already loaded!',13,10,'$'
  1018. not_loaded      db 'Fatal is not resident.  Use FATAL/I first.',13,10,'$'
  1019.  
  1020. reportPrefix    db 'FATAL v1.3 status:',13,10,'$'
  1021. errorCounts     db 'Critical errors.',13,10,'$'
  1022. autoCounts      db 'Automatic retries.','$'
  1023. drivePrefix     db 'Drive: $'
  1024. locusPrefix     db 'Locus:$'
  1025.  
  1026.  
  1027. ; ---------------------------------------------
  1028. ; initial installation
  1029. ;
  1030. entryPoint proc near
  1031.         push cs
  1032.         pop ds
  1033.         assume ds:code
  1034.  
  1035.         lea dx,signature
  1036.         call disps
  1037.  
  1038.         lea si,tail
  1039. checkTail:
  1040.         lodsb
  1041.         cmp al,13
  1042.         jz usage
  1043.  
  1044.         cmp al,'/'
  1045.         jz checkOption
  1046.         cmp al,'-'
  1047.         jz checkOption
  1048.         jmp checkTail
  1049.  
  1050. checkOption:
  1051.         lodsb
  1052.         and al,0ffh-20h         ;map to upper case
  1053.  
  1054.         cmp al,'C'
  1055.         jnz checkU
  1056.  
  1057.         call reportStats
  1058.         jmp exitProgram
  1059.  
  1060. checkU:
  1061.         cmp al,'U'
  1062.         jnz checkI
  1063.  
  1064.         call unInstall
  1065.         jmp exitProgram
  1066.  
  1067. checkI:
  1068.         cmp al,'I'
  1069.         jnz usage
  1070.         jmp newInstall
  1071.  
  1072.  
  1073. ; ---------------------------------------------
  1074. ; fatal/? - display license and usage messages
  1075. ;
  1076. usage:  mov al,tailLen
  1077.         cmp al,0
  1078.         lea dx,usages
  1079.         jnz exitWithMessage
  1080.  
  1081.         lea dx,license
  1082. ;       jmp exitWithMessage
  1083.  
  1084.  
  1085. ; ---------------------------------------------
  1086. exitWithMessage:
  1087.         call disps
  1088.  
  1089. exitProgram:
  1090.         msdos dosExit,0
  1091.  
  1092.  
  1093. ; ---------------------------------------------
  1094. ; fatal/I - new installation - hook vectors and go resident
  1095. ;
  1096. newInstall:
  1097.         msdos dosGetvers       ;verify dos 3 or later
  1098.         lea dx,need_dos30
  1099.         cmp al,2
  1100.         jle installExit
  1101.  
  1102.         call checkPresent
  1103.         lea dx,already_loaded
  1104.         jz installExit
  1105.  
  1106.         getvect 08h,old_int08           ;save original handler vectors
  1107.         getvect 21h,old_int21
  1108. ;       getvect 1ch,old_int1c
  1109.         getvect 24h,old_int24
  1110.  
  1111.         setvect 08h,int08_handler       ;install new handlers
  1112. ;       setvect 1ch,int1c_handler
  1113.         setvect 21h,int21_handler
  1114.  
  1115.         lea dx,fatal_loaded
  1116.         call disps
  1117.  
  1118.         lea dx,resident         ;terminate and stay resident
  1119.         int 27h
  1120.  
  1121. installExit:
  1122.         jmp exitWithMessage
  1123. entryPoint endp
  1124.  
  1125.  
  1126. ; =============================================
  1127. ; check if fatal is already present
  1128. ;
  1129. ; exit: Z       fatal is present,
  1130. ;               es-> resident code segment
  1131. ;
  1132. ;       NZ      not present
  1133. ;
  1134. checkPresent proc near
  1135.         msdos dosGetvec,24h    ;es:xx -> current int24 handler
  1136.  
  1137.         lea bx,signature        ;cs:bx -> local signature
  1138. checkNext:
  1139.         mov al,ds:[bx]          ;get next byte from local message
  1140.         cmp al,'$'              ;end of message?
  1141.         jz checkExit            ;already present if so
  1142.  
  1143.         cmp al,es:[bx]          ;compare next byte to int24 handler
  1144.         jnz checkExit           ;new installation if mismatch
  1145.  
  1146.         inc bx                  ;got a match, try the next char
  1147.         jmp checkNext
  1148.  
  1149. checkExit:
  1150.         ret
  1151. checkPresent endp
  1152.  
  1153.  
  1154. ; ---------------------------------------------
  1155. ; display message in code segment
  1156. ;
  1157. disps proc near
  1158.         push ds
  1159.         push cs
  1160.         pop ds
  1161.         msdos dosDisplay
  1162.         pop ds
  1163.         ret
  1164. disps endp
  1165.  
  1166.  
  1167. ; ---------------------------------------------
  1168. ; fatal/u - uninstall and exit
  1169. ;
  1170. unInstall proc near
  1171.         call checkPresent
  1172.         lea dx,not_loaded
  1173.         jnz unExit
  1174.  
  1175.         mov bx,es               ;bx->tsr code segment
  1176.         mov ax,ds
  1177.         sub ax,bx               ;calculate memory usage after fatal tsr
  1178.  
  1179.         lea dx,others_loaded    
  1180.         cmp ax,fatal_segs       ;amount of allowed overhead for DOS/PSP, etc.
  1181.         jge unExit              ;insure that others are not loaded after
  1182.  
  1183.         assume ds:nothing
  1184.         revect 21h,old_int21    ;unhook dos interrupt
  1185. ;       revect 1ch,old_int1c    ;unhook timer interrupt
  1186.         revect 08h,old_int08    ;unhook timer interrupt
  1187.         revect 24h,old_int24    ;unhook critical error interrupt
  1188.  
  1189.         push es
  1190.         mov es,es:envseg
  1191.         msdos dosFreemem       ;dealloc the tsr's environment segment
  1192.  
  1193.         pop es              
  1194.         msdos dosFreemem       ;dealloc the tsr's code segment
  1195.  
  1196.         push cs
  1197.         pop ds
  1198.         assume ds:code
  1199.  
  1200.         lea dx,fatal_removed
  1201. unExit:
  1202.         call disps
  1203.         ret
  1204. unInstall endp
  1205.  
  1206.  
  1207. ; ---------------------------------------------
  1208. ; fatal/C - report critical error counts
  1209. ;
  1210. reportStats proc near
  1211.         call checkPresent
  1212.         lea dx,not_loaded
  1213.         jnz reportExit
  1214.  
  1215.         push es
  1216.         pop ds
  1217.         lea dx,reportPrefix
  1218.         mov ax,errorCount
  1219.         call decimal
  1220.  
  1221.         lea dx,errorCounts
  1222.         mov ax,autoCount
  1223.         call decimal
  1224.  
  1225.         lea dx,autoCounts
  1226.         call disps
  1227.  
  1228.         mov ax,errorCount
  1229.         cmp ax,0
  1230.         jz reportFinish         ;finish now if no errors to report
  1231.  
  1232.         lea si,errorNames
  1233.         mov dx,si
  1234.         call dumpTable
  1235.  
  1236.         lea si,classNames
  1237.         mov dx,si
  1238.         call dumpTable
  1239.  
  1240.         lea si,locusNames
  1241.         lea dx,locusPrefix
  1242.         call dumpTable
  1243.  
  1244.         lea si,driveNames
  1245.         lea dx,drivePrefix
  1246.         call dumpTable
  1247.  
  1248.         lea si,areaNames
  1249.         lea dx,areaPrefix
  1250.         call dumpTable
  1251.  
  1252.         lea si,suggestNames
  1253.         mov dx,si
  1254.         call dumpTable
  1255.  
  1256. reportFinish:
  1257.         lea dx,crlfs
  1258. reportExit:
  1259.         call disps
  1260.         ret
  1261. reportStats endp
  1262.  
  1263.  
  1264. ;-------------------------------------------------------------
  1265. ; dumpTable - display usage counts for a code table
  1266. ; entry:  ds:si = table head
  1267. ;            dx = table name
  1268. ;
  1269. dumpTable proc near
  1270.         push dx
  1271.         lea dx,crlfs
  1272.         call disps
  1273.         pop dx
  1274.         call disps
  1275.  
  1276. dumpNext:
  1277.         lodsb                   ;skip to the end of the message
  1278.         cmp al,'$'
  1279.         jnz dumpNext
  1280.  
  1281.         lodsw                   ;get entry code+activity count
  1282.         cmp ah,0                ;skip entries with count=0
  1283.         jnz dumpEntry
  1284.         jmp dumpAgain
  1285.  
  1286. dumpEntry:
  1287.         push ax
  1288.         mov al,ah
  1289.         clr ah
  1290.         lea dx,crlfs
  1291.         call decimal
  1292.  
  1293.         mov dx,si
  1294.         call disps
  1295.         pop ax
  1296.  
  1297. dumpAgain:
  1298.         cmp al,0
  1299.         jnz dumpNext
  1300.  
  1301.         ret
  1302. dumpTable endp
  1303.  
  1304.  
  1305. ; ---------------------------------------------
  1306. ; convert number to decimal
  1307. ;       dx  initial message
  1308. ;       ax  number to convert
  1309. ;
  1310. decBuf db '00000'
  1311. decEnd db ' $'
  1312.  
  1313. decimal proc near
  1314.         assume ds:nothing
  1315.         push si
  1316.  
  1317.         push ax
  1318.         call disps
  1319.         pop ax
  1320.  
  1321.         lea bx,decBuf
  1322.         mov cx,5
  1323.         mov dl,' '
  1324. decClear:
  1325.         mov cs:[bx],dl
  1326.         inc bx
  1327.         loop decClear
  1328.  
  1329.         mov cx,5        ;convert 5 digits
  1330.         mov si,10       ;used to divide by 10
  1331.  
  1332. decNext:
  1333.         clr dx          ;convert AX to doubleword in DX:AX
  1334.  
  1335.         div si          ;divide number by 10. Remainder is in
  1336.                         ; DX--this is a one-digit decimal
  1337.                         ; number.  Number/10 is in AX
  1338.  
  1339.         add dl,'0'      ;convert remainder to a text character
  1340.         dec bx          ;put this digit in the string and
  1341.         mov cs:[bx],dl  ;point to the location for the
  1342.                         ; next most-significant digit
  1343.         cmp ax,0
  1344.         jz decLast      ;stop when 0 is reached
  1345.  
  1346.         loop decNext
  1347.  
  1348. decLast:
  1349.         lea dx,decBuf
  1350.         call disps
  1351.  
  1352.         pop si
  1353.         ret
  1354. decimal endp
  1355.  
  1356.  
  1357. code ends
  1358.         end entry
  1359.  
  1360.